#include <bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN 200005
#define LOGN 31

// Trie树相关变量定义
int nodecnt, rt;         // nodecnt: Trie树节点计数器, rt: Trie树根节点
int son[MAXN * LOGN][2]; // son数组: Trie树节点结构，每个节点有2个子节点(0和1)


int f[MAXN * LOGN][2];   // f数组: 记忆化数组，用于存储DFS计算结果

int n, m, a[MAXN]; // n: 数字个数, m: 上界, a: 存储输入的数字数组

// Trie树插入函数 - 将数字x的二进制表示插入到Trie树中
// t: 当前节点指针的引用, x: 要插入的数字, k: 当前处理的二进制位(从高位到低位)
void insert(int &t, int x, int k) {
  if (!t)          // 如果当前节点不存在
    t = ++nodecnt; // 创建新节点
  if (k == -1)     // 如果所有位都处理完毕
    return;
  int ch = x >> k & 1;          // 获取x的第k位二进制值(0或1)
  insert(son[t][ch], x, k - 1); // 递归插入到对应的子节点
}

// DFS函数 - 在Trie树上进行深度优先搜索，计算满足条件的异或对数量
// x: 当前Trie节点, k: 当前处理的二进制位, up: 是否受到上界m的限制
int dfs(int x, int k, int up) {
  if (k == -1) // 如果所有位都处理完毕
    return 0;
  if (f[x][up] != -1) // 如果已经计算过当前状态，直接返回记忆化结果
    return f[x][up];

  int res = 0;                  // 结果计数器
  int upt = (m >> k & 1) || up; // 判断当前位是否受到上界限制

  // 遍历当前节点的两个可能的子节点(0和1)
  for (int ch = 0; ch <= upt; ch++) {
    int nup = up && ch == upt; // 更新下一层的上界限制状态

    if (son[x][ch]) { // 如果Trie树中存在当前字符对应的子节点
      res += dfs(son[x][ch], k - 1, nup); // 递归处理子节点
    } else {
      // 如果Trie树中不存在当前字符对应的子节点
      // 计算缺失子树的大小(即所有可能的叶子节点数量)
      int rleaves = nup ? (m & ((1 << k) - 1)) + 1 : 1 << k;
      // 处理另一个子节点，并加上缺失子树的总贡献
      res += dfs(son[x][ch ^ 1], k - 1, nup) + (1ll << k) * rleaves;
    }
  }
  return f[x][up] = res; // 记忆化存储结果并返回
}

signed main() {
  memset(f, -1, sizeof(f));  // 初始化记忆化数组为-1
  scanf("%lld%lld", &n, &m); // 读取n和m
  m--;                       // m减1，因为题目要求小于等于m

  // 构建Trie树：将每个数字插入到Trie树中
  for (int i = 1; i <= n; i++) {

    scanf("%lld", &a[i]);
    insert(rt, a[i], 30); // 插入每个数字到Trie树
  }

  // 在Trie树上进行DFS计算，输出结果
  printf("%lld\n", dfs(rt, 30, 1));
  return 0;
}